export default class Snake {
  /**表示舌头的元素**/
  head: HTMLElement;
  /**表示蛇身**/
  bodies: HTMLCollection; //会自动补充新元素
  snakeEl: HTMLElement;

  constructor() {
    //单独获取snake
    this.snakeEl = document.getElementById("snake")!;
    //注意querySelector查询内容是静态的 动态添加不会更新，例如有10个更新11个依然拿到10个
    this.head = document.querySelector("#snake")!.firstChild as HTMLElement;
    //下面的获取方式可以动态获取
    this.bodies = this.snakeEl!.getElementsByTagName("div");
  }

  get X() {
    return this.head.offsetLeft;
  }

  get Y() {
    return this.head.offsetTop;
  }

  set X(value: number) {
    //判断看是否发生变化
    if (value == this.X) {
      return;
    }

    //X是否合法范围 看是否超过范围
    if (value < 0 || value > 290) {
      throw new Error("蛇撞墙了！！！");
    }

    //蛇头不能闯到自己身体 也就是蛇头向左的时候不能向右掉头，反之也是
    if (
      this.bodies[1] &&
      (this.bodies[1] as HTMLElement).offsetLeft === value
    ) {
      //如果发生掉头蛇向反方向继续移动,如果蛇当前位置大于this.X
      if (value > this.X) {
        value = this.X - 10;
      } else {
        value += this.X + 10;
      }
    }
    this.moveBody();
    this.head.style.left = value + "px";
    //检查有没有撞到自己
    this.checkHeaderBody();
  }

  set Y(value: number) {
    if (value == this.Y) {
      return;
    }

    //X是否合法范围 看是否超过范围
    if (value < 0 || value > 290) {
      throw new Error("蛇撞墙了！！！");
    }
    //蛇头不能闯到自己身体 也就是蛇头向左的时候不能向右掉头，反之也是
    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
      //如果发生掉头蛇向反方向继续移动,如果蛇当前位置大于this.Y
      if (value > this.Y) {
        value = this.Y - 10;
      } else {
        value = this.Y + 10;
      }
    }
    this.moveBody();
    this.head.style.top = value + "px";
    //检查有没有撞到自己
    this.checkHeaderBody();
  }

  //添加身体
  addBody() {
    //向蛇中增加div元素
    this.snakeEl.insertAdjacentHTML("beforeend", "<div></div>");
  }

  //移动身体
  moveBody() {
    /** 将蛇头后面的身体设置为前边身体的位置
     * 举例子
     * 第4节 = 第3年的位置
     * 第3年 = 第2节的位置
     * 第2接 = 舌头的位置
     **/
    //当前身体的位置
    for (let i = this.bodies.length - 1; i > 0; i--) {
      let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
      let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;
      // 将值设置在当前的身体上
      (this.bodies[i] as HTMLElement).style.left = X + "px";
      (this.bodies[i] as HTMLElement).style.top = Y + "px";
    }
  }
  //检查头和身体有没有相撞
  checkHeaderBody() {
    //获取所有身体坐标检查是否和身体重合
    for (let i = 1; i < this.bodies.length; i++) {
      let bodyEl = this.bodies[i] as HTMLElement;
      if (this.X === bodyEl.offsetLeft && this.Y === bodyEl.offsetTop) {
        //说明蛇头撞到身体
        throw new Error("撞到自己身体了");
      }
    }
  }
}
